package com.dwxt.common.util;

import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author: YanLong
 * @Description:OkHttp3 工具类
 * @Date: Created in 10:53 2019/9/17
 */
@Slf4j
public class OkHttpUtils {

    private static final int readTimeout = 30;

    private static final int writeTimeout = 30;

    private static final int connectTimeout = 3;

    private static final boolean proxyIsAble = false;

    private static final String proxyHostAddress = "localhost";

    private static final int proxyPort = 1080;

    private static final String proxyUser = "*** Provide your proxy user ***";

    private static final String proxyPassword = "*** Provide your proxy password ***";

    private static OkHttpClient GetHttpClient() {
        X509TrustManager xtm = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                X509Certificate[] x509Certificates = new X509Certificate[0];
                return x509Certificates;
            }
        };

        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, new TrustManager[]{xtm}, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            log.error(e.toString());
        } catch (KeyManagementException e) {
            log.error(e.toString());
        }

        HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        };

        OkHttpClient.Builder builder = new OkHttpClient.Builder().followRedirects(false).retryOnConnectionFailure(false)
                .sslSocketFactory(sslContext.getSocketFactory(), xtm).hostnameVerifier(DO_NOT_VERIFY).cache(null)
                .connectTimeout(connectTimeout, TimeUnit.SECONDS).readTimeout(readTimeout, TimeUnit.SECONDS)
                .writeTimeout(writeTimeout, TimeUnit.SECONDS);

        if (proxyIsAble) {
            builder.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHostAddress, proxyPort)));

            Authenticator proxyAuthenticator = new Authenticator() {
                @Override
                public Request authenticate(Route route, Response response) throws IOException {
                    String credential = Credentials.basic(proxyUser, proxyPassword);
                    return response.request().newBuilder()
                            .header("Proxy-Authorization", credential)
                            .build();
                }
            };
            builder.proxyAuthenticator(proxyAuthenticator);
        }
        return builder.build();
    }


    /**
     * get 同步请求
     */

    public static String synGet(String url, Map<String, String> headers) {
        Request.Builder reqBuilder = new Request.Builder();
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                //reqBuilder.header(entry.getKey(),entry.getValue());
                reqBuilder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        Request request = reqBuilder.url(url).build();
        String response = getResponseString(request);
        return response;
    }

    /**
     * post 表单请求
     */
    public static String formPost(String url, Map<String, String> params, Map<String, String> headers) {

        /** 加入参数*/
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                builder.add(key, value);
            }
        }
        /**加入header*/
        Request.Builder reqBuilder = new Request.Builder();
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                //reqBuilder.header(entry.getKey(),entry.getValue());
                reqBuilder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        Request request = reqBuilder.url(url).post(builder.build()).build();
        String response = getResponseString(request);
        return response;
    }

    /**
     * post json请求
     */
    public static String jsonPost(String url, String jsonParam, Map<String, String> headers) {

        /** 加入参数*/
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSON, jsonParam);
        Request.Builder builder = new Request.Builder().url(url).post(body);
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        Request request = builder.build();
        String response = getResponseString(request);
        return response;
    }

    /**
     * 上传文件
     *
     * @param url
     * @param file
     * @param typeName
     * @return
     * @throws IOException
     */
    public static String uploadFile(String url, File file, String typeName, Map<String, String> params) {
        MultipartBody.Builder builder = new MultipartBody.Builder();
        if (params != null) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                builder.addFormDataPart(entry.getKey(), entry.getValue());
            }
        }
        RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
        MultipartBody body = builder.setType(MultipartBody.FORM)
                .addFormDataPart(typeName, file.getName(), fileBody)
                .build();
        Request request = new Request.Builder()
                .post(body)
                .url(url)
                .build();
        return getResponseString(request);
    }


    private static String getResponseString(Request request) {
        OkHttpClient okHttpClient = GetHttpClient();
        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
            String body = response.body().string();
            log.info("response:{}", body);
            return body;
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return null;
    }

}
